<?php
require_once dirname(dirname(dirname(__FILE__))) . '/init.php';
/**
 *计算a,b,c需求
 */
class Story extends Controller_CronJob {

	public function run() {
/*		$aStart = time();
if (!$this->_storyA()) {
exit('a story error');
}
$aEnd = time();
echo "需求A耗时:" . ($aEnd - $aStart);
echo "\r\n";*/

		if (!$this->_storyB()) {
			exit('b story error');
		}
		$cStart = time();
		if (!$this->_storyC()) {
			exit('c story error');
		}
		$cEnd = time();
		echo "需求C耗时:" . ($cEnd - $cStart);
		echo "\r\n";

		$limitStart = time();
		if (!$this->_storyQuantityLimit()) {
			exit('story quantity limit error');
		}
		$limitEnd = time();
		echo "需求数量限制耗时:" . ($limitEnd - $limitStart);
		echo "\r\n";

		$transferStart = time();
		if (!$this->_applyTransfer()) {
			exit('story apply transfer error');
		}
		$transferEnd = time();
		echo "需求调拨   耗时:" . ($transferEnd - $transferStart);
		echo "\r\n";

		//需求是否需要审核
		if (!$this->_updateExamineStatus()) {
			exit('update examine status error');
		}
		echo '计算完成！';
		exit('需求计算完成！');
	}

	/**
	 * 生成缺货需求(A需求)
	 * @return [type] [description]
	 */
	protected function _storyA() {
		/**
		 * 考虑到可能的主从延迟，查询使用主库
		 * @var [type]
		 */
/*		$stockoutProductCalculate = $this->writeDb->fetchALL('call get_stockout_product()');
if (!$stockoutProductCalculate) {
$this->log->record('统计缺货商品出现错误！', Log::ALERT);
return false;
}*/

		$stockoutStoryModel = new Cron_Model_Backup_StockoutStory();
		$calStockoutStoryRe = $stockoutStoryModel->create();
		if ($calStockoutStoryRe === false) {
			$errorMsg = "计算备货需求的A需求发生错误，原因是:" . $stockoutStoryModel->getErrorMsg();
			$this->log->record($errorMsg, Log::ALERT);
			return false;
		}
		$this->log->record("A需求计算完成！");
		return true;
	}

	protected function _storyB() {
		$wdb = Model_Db::getInstance('write_db');
		$special_purchase_model = new Cron_Model_Backup_SpecialPurchase();
		// 获取返回的回货总数
		$total = $special_purchase_model->getGoodsReturnAcount();
		$limit = 100; // 每次执行数目
		for ($i = 0; $i < ceil($total / $limit); $i++) {
			$return = $special_purchase_model->getGoodsReturn(($i * $limit), $limit);
			if ($return) {
				foreach ($return as $sku => $log) {
					// 更新每个sku为一个事务单元
					$wdb->beginTransaction();
					try {
						// 记录总回货
						$return_total = $log['back_quantity'];
						// 获取对应的特采记录
						$specials = $special_purchase_model->getSpecialPurchases($log['goods_sn'], $log['stock_sn'], $log['plat_code']);
						if ($specials) {
							foreach ($specials as $s) {
								// 特采待采数量
								$wait_total = $s['apply_num'] - $s['return_num'];
								// 总回货剩余大于0
								if ($return_total > 0) {
									// 如果回货数量大于等于待采数量
									if ($return_total >= $wait_total) {
										$special_purchase_model->returnSpecialGoods($s['id'], $wait_total, '1');
										$return_total = $return_total - $wait_total;
									} else {
										// 不够待采，更新为部分采购，停止对其他特采的更新
										$special_purchase_model->returnSpecialGoods($s['id'], $return_total, '3');
										$return_total = 0;
									}
								}
							}
							// 更新回货记录状态
							$special_purchase_model->finishGoodsReturn($log['id']);
							$wdb->commit();
						}
					} catch (Exception $e) {
						$wdb->rollBack();
						$this->log->record("特采回货发生错误，原因:" . $e->getMessage(), Log::ALERT);
						return false;
					}
				}
			}
		}
		// 生成B需求
		$b_storys = $special_purchase_model->getUnfinshPurchase();
		$story = new Application_Model_Story();
		foreach ($b_storys as $b) {
			$res = $story->create($b['goods_sn'], $b['warehouse_code'], 'b', $b['wait_num'], $b['platform_code']);
			if ($res === false) {
				$this->log->record($story->getErrorMsg());
			}
		}

		$this->log->record("B需求计算完成！");
		return true;
	}

	/**
	 * 生成自动备货需求(c需求)
	 * @return [type] [description]
	 */
	protected function _storyC() {
/*		$_30days_has_sales_product = $this->writeDb->fetchALL('call get_30days_has_sales_product()');
if (!$_30days_has_sales_product) {
$this->log->record('统计30天内有销量的商品出现错误！', Log::ALERT);
return false;
}*/

		$backupRuleModel = new Cron_Model_Backup_BackupRule();
		$availableRuleList = $backupRuleModel->getAvailableRule();
		if (empty($availableRuleList)) {
			$errorMsg = "不存在任何自动备货规则！";
			$this->log->record($errorMsg, Log::ALERT);
			return false;
		}

		foreach ($availableRuleList as $oneBackupRule) {
			$runResult = $backupRuleModel->run($oneBackupRule['id']);
			if ($runResult === false) {
				$this->log->record("C需求计算发生错误，原因:" . $backupRuleModel->getErrorMsg(), Log::ALERT);
			}
		}
		$this->log->record("C需求计算完成！");
		return true;
	}

	/**
	 * 商品需求数量限制
	 * @return [type] [description]
	 */
	protected function _storyQuantityLimit() {
		$where = $this->_where();

		$waitCheckStoryNum = $this->writeDb->fetchOne('select count(*) from b_story where ' . $where);
		if (!$waitCheckStoryNum) {
			return true;
		}

		$storyModel = new Cron_Model_Backup_Story();
		$everyTimeHandleNum = 2000;
		$handleTimes = ceil($waitCheckStoryNum / $everyTimeHandleNum);

		$stockTransferApplyModel = new Cron_Model_Backup_StockTransferApply();
		for ($i = 0; $i < $handleTimes; $i++) {
			$offset = $i * $everyTimeHandleNum;
			$waitCheckStoryList = $this->writeDb->fetchAll('select * from b_story where ' . $where . " limit $offset,$everyTimeHandleNum ");

			foreach ($waitCheckStoryList as $_oneStory) {
				$quantityLimitResult = $storyModel->storyQuantityLimit($_oneStory);
				if ($quantityLimitResult === false) {
					$this->log->record("需求数量限制计算时发生错误,原因：" . $storyModel->getErrorMsg(), Log::ALERT);
				}
			}
		}
		return true;
	}

	/**
	 * 需求调拨申请
	 * @return [type] [description]
	 */
	protected function _applyTransfer() {
		$where = $this->_where();
		$stockTransferWarehouseModel = new Cron_Model_Backup_TransferWarehouse();
		$canTransferWarehouse = $stockTransferWarehouseModel->canApplyTransferWarehouse();
		if (!$canTransferWarehouse) {
			return true;
		}
		$canTransferWarehouse = $stockTransferWarehouseModel->getCanTransferWarehouseOrderByPrior();
		foreach ($canTransferWarehouse as $warehouse) {
			$transferYbWarehouseWhere = $where . ' AND warehouse_code=' . $this->writeDb->quote($warehouse);
			$this->_doApplyTransfer($transferYbWarehouseWhere);
		}

		return true;
	}

	protected function _doApplyTransfer($where) {
		$waitTransferStoryNum = $this->writeDb->fetchOne('select count(*) from b_story where ' . $where);
		if (!$waitTransferStoryNum) {
			return true;
		}

		$everyTimeHandleNum = 2000;
		$handleTimes = ceil($waitTransferStoryNum / $everyTimeHandleNum);

		$stockTransferApplyModel = new Cron_Model_Backup_StockTransferApply();
		for ($i = 0; $i < $handleTimes; $i++) {
			$offset = $i * $everyTimeHandleNum;
			$waitTransferStoryList = $this->writeDb->fetchAll('select * from b_story where ' . $where . " limit $offset,$everyTimeHandleNum ");
			foreach ($waitTransferStoryList as $_oneBackupStory) {
				$transferApplyResult = $stockTransferApplyModel->apply($_oneBackupStory);
				if ($transferApplyResult === false) {
					$this->log->record('需求' . $_oneBackupStory['id'] . '调拨申请出错,原因:' . $stockTransferApplyModel->getErrorMsg());
				}
			}
		}
		return true;
	}

	/**
	 * 更新需求审核状态
	 * 检查需求是否需要小组长审核，如果不需要，直接审核通过需求，并将需求传输pms，如果需要
	 * 更新需求审核状态到“待小组长审核”
	 * @return [type] [description]
	 */
	protected function _updateExamineStatus() {
		$where = $this->_where();
		//只检查无需调拨的需求是否需要小组长审核，需要调拨的需求在调拨申请审核后检查
		$where .= " AND is_apply_stock_transfer=0";
		$waitUpdateStatusStoryNum = $this->writeDb->fetchOne('select count(*) from b_story where ' . $where);

		if (!$waitUpdateStatusStoryNum) {
			return true;
		}

		$everyTimeHandleNum = 2000;
		$handleTimes = ceil($waitUpdateStatusStoryNum / $everyTimeHandleNum);

		$storyModel = new Application_Model_Story();

		for ($i = 0; $i < $handleTimes; $i++) {
			$offset = $i * $everyTimeHandleNum;
			$waitTransferStoryList = $this->writeDb->fetchAll('select id from b_story where ' . $where . " limit $offset,$everyTimeHandleNum ");
			foreach ($waitTransferStoryList as $_oneBackupStory) {
				try {
					$primaryTeamLeaderModel = new Application_Model_StoryStatus_PrimaryTeamLeaderStatus($_oneBackupStory['id']);
					$storyNeedCheck = $primaryTeamLeaderModel->needCheck();
				} catch (Exception $e) {
					$this->log->record('需求' . $_oneBackupStory['id'] . '在检查是否需要小组长审核是发生错误,原因是:' . $e->getMessage(), Log::WARN);
					continue;
				}

				$this->writeDb->beginTransaction();
				try {
					if ($storyNeedCheck) {
						$updatedStatus = Application_Model_Story::WAIT_PRIMARY_TEAM_LEADER_EXAMINE;
					} else {
						$updatedStatus = Application_Model_Story::EXAMINE_PASS;
					}
					$statusUpdateResult = $storyModel->statusUpdate($_oneBackupStory['id'], $updatedStatus, false);
					if ($statusUpdateResult === false) {
						$this->log->record('需求' . $_oneBackupStory['id'] . '在更新审核状态时发生错误,原因是:' . $storyModel->getErrorMsg(), Log::WARN);
						$this->writeDb->rollBack();
						continue;
					}

					//记录需求审核日志
					if ($updatedStatus == Application_Model_Story::EXAMINE_PASS) {
						$examineLog['handle_user'] = 'system';
						$examineLog['story_id'] = $_oneBackupStory['id'];
						$examineLog['handle_role'] = "系统";
						$examineLog['handle_type'] = 1;
						$this->writeDb->insert('b_story_examine_log', $examineLog);
					}

					$this->writeDb->commit();
				} catch (Exception $e) {
					$this->log->record('需求' . $_oneBackupStory['id'] . '在检查是否需要小组长审核是发生错误,原因是:' . $e->getMessage(), Log::WARN);
					$this->writeDb->rollBack();
				}
			}
		}
		return true;
	}

	protected function _where() {
		$where = '';
		$where = " create_date=" . $this->writeDb->quote(date("Y-m-d"));
		$where .= " AND examine_status=" . Application_Model_Story::INIT_EXAMINE_STATUS;
		$where .= " AND delete_flag=0";
		return $where;
	}
}

$story = new Story();
$story->run();